package com.sec.etech.form.cust.service;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.openbpm.base.api.exception.BusinessMessage;
import org.openbpm.base.api.query.QueryOP;
import org.openbpm.base.api.response.impl.ResultMsg;
import org.openbpm.base.core.id.IdUtil;
import org.openbpm.base.core.model.BaseModel;
import org.openbpm.base.core.util.ExceptionUtil;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.base.db.model.query.DefaultQueryFilter;
import org.openbpm.form.dao.FormCustSqlDao;
import org.openbpm.form.manager.FormCustSqlFieldsManager;
import org.openbpm.form.manager.FormCustSqlRelationManager;
import org.openbpm.form.manager.impl.FormCustSqlManagerImpl;
import org.openbpm.form.model.custsql.FormCustSql;
import org.openbpm.form.model.custsql.FormCustSqlFields;
import org.openbpm.form.model.custsql.FormCustSqlRelation;
import org.openbpm.form.util.*;
import org.openbpm.form.vo.SqlButtonVO;
import org.openbpm.form.vo.SqlConditionVO;
import org.openbpm.form.vo.SqlFieldsVO;
import org.openbpm.sys.api.freemark.IFreemarkerEngine;
import org.openbpm.sys.core.dao.SysTreeNodeDao;
import org.openbpm.sys.core.model.SysTreeNode;
import org.openbpm.sys.util.ContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service("etechFormCustSqlManager")
public class EtechFormCustSqlManager extends FormCustSqlManagerImpl {

    @Resource
    FormCustSqlDao formCustSqlDao;

    @Resource
    FormCustSqlFieldsManager formCustSqlFieldsManager;

    @Autowired
    FormCustSqlRelationManager formCustSqlRelationMananger;

    @Autowired
    IFreemarkerEngine freemarkerEngine;

    @Resource
    SysTreeNodeDao sysTreeNodeDao;

    public ResultMsg<List<SqlFieldsVO>> parseSql(FormCustSql formCustSql) {
        JSONObject expandJo = JSONObjectUtil.parseExpand(formCustSql.getExpand());
        String bpmExt = expandJo.getString("bpmExt");
        if (StringUtil.isEmpty(bpmExt)) {
            return parseSql2(formCustSql);
        }
        String taskSql = EtechTaskSqlHelper.getBpmTaskSqlByExtType(bpmExt);
        if (StringUtil.isEmpty(taskSql)) {
            return parseSql2(formCustSql);
        }

        String sqlContext = formCustSql.getSqlContent();

//        String sqlId = formCustSql.getId();
//        if (StringUtil.isNotEmpty(sqlId)) {
//            List<FormCustSqlFields> fieldsList = this.formCustSqlFieldsManager.getListBySqlId(sqlId);
//        }

        //ResultMsg<List<SqlFieldsVO>> resultMsg = super.parseSql(formCustSql);
        ResultMsg<List<SqlFieldsVO>> resultMsg = parseSql2(formCustSql);
        List<SqlFieldsVO> fieldsVOList = resultMsg.getData();
        Set<String> setFieldName = new HashSet<>();

        for (SqlFieldsVO fieldsVO : fieldsVOList) {
            if(fieldsVO==null || fieldsVO.getFieldName()==null){
                continue;
            }
            if(!"task".equals(fieldsVO.getTableAlias())){
                fieldsVO.setTableAlias("bus");
            }
            if ("bpm_task_ext".equalsIgnoreCase(fieldsVO.getFieldName())) {
                fieldsVO.setHidden(1);
            }
            setFieldName.add(fieldsVO.getFieldName().toLowerCase());
        }

        formCustSql.setSqlContent(taskSql);
        //ResultMsg<List<SqlFieldsVO>> resultMsg1 = super.parseSql(formCustSql);
        ResultMsg<List<SqlFieldsVO>> resultMsg1 = parseSql2(formCustSql);
        int index = 0;
        //从某个特定字段bpm_task_ext处开始插入
        if (setFieldName.contains("bpm_task_ext")) {
            for (SqlFieldsVO fieldsVO : fieldsVOList) {
                index++;
                if ("bpm_task_ext".equals(fieldsVO.getFieldName().toLowerCase())) {
                    break;
                }
            }
        }
        List<SqlFieldsVO> fieldsVOList1 = resultMsg1.getData();
        Set<String> removeFields = getRemoveFieldsInTodo();
        Set<String> showFileds = getShowFieldsInTodo();

        for (SqlFieldsVO taskField : fieldsVOList1) {
            String fieldName = taskField.getFieldName().toLowerCase();
            if (setFieldName.contains(fieldName)) {
                continue;
            }
            taskField.setTableAlias("task");
            if ("task_id_".equalsIgnoreCase(fieldName)) {
                //设置控件类型-21任务，格式task-info
                taskField.setControlType(21);
                taskField.setDateFormat("task-info");
            }
            if ("remain_days_".equalsIgnoreCase(fieldName)) {
                //设置控件类型-21任务，格式 remaindays
                taskField.setControlType(21);
                taskField.setDateFormat("remaindays");
            }
            // 待处理任务的显示字段或删除字段
            if (bpmExt.startsWith("todotask_") || bpmExt.startsWith("dealtask")) {
                if (removeFields.contains(fieldName)) {
                    continue;
                }
                if (showFileds.contains(fieldName)) {
                    taskField.setHidden(0);
                } else {
                    taskField.setHidden(1);
                }
            }
            fieldsVOList.add(index, taskField);
            index++;
        }
        formCustSql.setSqlContent(sqlContext);
        if (fieldsVOList != null) {
            resultMsg.setData(fieldsVOList);
        }
        return resultMsg;
    }

    public ResultMsg<List<SqlFieldsVO>> parseSql2(FormCustSql formCustSql) {
        // copy from super.parseSql(FormCustSql)
        // super.parseSql(formCustSql);

        String sqlId = formCustSql.getId();
        String sql = formCustSql.getSqlContent();
        String dsKey = formCustSql.getDsKey();

        Map<String, Object> reJson = new HashMap<>();
        reJson.put("startTime","now()");
        reJson.put("endTime","now()");
        sql = this.freemarkerEngine.parseByString(sql, reJson);
        sql = getSql(sql);
        sql = removeDataSql(sql);

        ResultMsg<String> executeSql = JdbcTemplateUtil.executeSql(dsKey, sql);
        if (!executeSql.getIsOk().booleanValue()) {
            this.logger.error("解析sql异常:{}", executeSql.getMsg());
            return ResultMsg.ERROR(executeSql.getMsg());
        }

        // 解析SQL字段

        ResultMsg<List<SqlFieldsVO>> rsp = getFieldListBySql(dsKey, sql);
        if (!rsp.getIsOk().booleanValue()) {
            return ResultMsg.ERROR(rsp.getMsg());
        }
        List<SqlFieldsVO> fields = (List<SqlFieldsVO>) rsp.getData();

        // TODO 增加流程字段？


        // 检查原来字段配置
        if (StringUtil.isNotEmpty(sqlId)) {
            List<FormCustSqlFields> fieldsList = this.formCustSqlFieldsManager.getListBySqlId(sqlId);
            if(!CollectionUtils.isEmpty(fieldsList)){
                Map<String, FormCustSqlFields> mFiledsOld = new HashMap<>();
                for (FormCustSqlFields oldFields : fieldsList){
                    mFiledsOld.put(oldFields.getFieldName(), oldFields);
                }
                for (SqlFieldsVO field : fields) {
                    if(mFiledsOld.containsKey(field.getFieldName())){
                        initFiledWithOld(field, mFiledsOld.get(field.getFieldName()));
                    }
                } // end for fields
            }
            Collections.sort(fields, new Comparator<SqlFieldsVO>(){
                @Override
                public int compare(SqlFieldsVO o1, SqlFieldsVO o2) {
                    return o1.getSn()-o2.getSn();
                }
            });
        }
        return rsp;
    }

    private SqlFieldsVO initFiledWithOld(SqlFieldsVO field, FormCustSqlFields oldFields){
        if (oldFields.getFieldName().equals(field.getFieldName())) {
            if (StringUtil.isNotEmpty(oldFields.getFieldDesc())) {
                field.setFieldDesc(oldFields.getFieldDesc());
            }
            if (StringUtil.isNotEmpty(oldFields.getAlign())) {
                field.setAlign(oldFields.getAlign());
            }
            if (StringUtil.isNotEmpty(oldFields.getHidden())) {
                field.setHidden(oldFields.getHidden());
            }
            if (StringUtil.isNotEmpty(oldFields.getUnit())) {
                field.setUnit(oldFields.getUnit());
            }
            if (StringUtil.isNotEmpty(oldFields.getWidth())) {
                field.setWidth(oldFields.getWidth());
            }
            if (StringUtil.isNotEmpty(oldFields.getUnit())) {
                field.setUnit(oldFields.getUnit());
            }
            // 排序字段，强制更新
            if (StringUtil.isNotEmpty(oldFields.getSn())) {
                field.setSn(oldFields.getSn());
            }
            if (StringUtil.isNotEmpty(oldFields.getHref())) {
                field.setHref(oldFields.getHref());
            }
            if (StringUtil.isNotEmpty(oldFields.getControlType())) {
                field.setControlType(oldFields.getControlType());
            }
            if (StringUtil.isNotEmpty(oldFields.getDateFormat())) {
                field.setDateFormat(oldFields.getDateFormat());
            }
            if (StringUtil.isNotEmpty(oldFields.getExpand())) {
                field.setExpand(oldFields.getExpand());
            }
            if (StringUtil.isNotEmpty(oldFields.getAddAble())) {
                field.setAddAble(oldFields.getAddAble());
            }
            if (StringUtil.isNotEmpty(oldFields.getEditAble())) {
                field.setEditAble(oldFields.getEditAble());
            }
            if (StringUtil.isNotEmpty(oldFields.getImportAble())) {
                field.setImportAble(oldFields.getImportAble());
            }
            if (StringUtil.isNotEmpty(oldFields.getExportAble())) {
                field.setExportAble(oldFields.getExportAble());
            }
            if (StringUtil.isNotEmpty(oldFields.getRules())) {
                field.setRules(oldFields.getRules());
            }
            if (StringUtil.isNotEmpty(oldFields.getPlaceholder())) {
                field.setPlaceholder(oldFields.getPlaceholder());
                if (StringUtil.isNotEmpty(oldFields.getFuzz())) {
                    field.setFuzz(oldFields.getFuzz());
                }
            }
        } // end if
        return field;
    }

    public static String removeDataSql(String sql) {
        try {
            Select select = (Select) CCJSqlParserUtil.parse(sql.trim());
            PlainSelect selectBody = (PlainSelect) select.getSelectBody();
            Object object = selectBody.getWhere();
            if (object == null) {
                EqualsTo equalsTo = new EqualsTo();
                equalsTo.setLeftExpression((Expression) new Column("1"));
                equalsTo.setRightExpression((Expression) new LongValue("1"));
                object = equalsTo;
            } else {
                // TODO 待验证
                EqualsTo equalsTo = new EqualsTo();
                equalsTo.setLeftExpression((Expression) new Column("1"));
                equalsTo.setRightExpression((Expression) new LongValue("2"));
                object = equalsTo;
                //object = new AndExpression((Expression) object, (Expression) equalsTo);
            }
            selectBody.setWhere((Expression) object);

            return select.toString();
        } catch (Exception e) {
            e.printStackTrace();
            //log.error("sql解析异常，sql: {}, e:{}", new Object[]{sql, e.getMessage(), e});
            return null;
        }
    }

    private ResultMsg<List<SqlFieldsVO>> getFieldListBySql(String dsKey, String sql) {
        TableOperUtil tableOperUtil = new TableOperUtil();
        ResultMsg<List<SqlFieldsVO>> fieldListRsp = tableOperUtil.getColumnModalBySql(sql, dsKey);
        if (!fieldListRsp.getIsOk().booleanValue()) {
            return ResultMsg.ERROR(fieldListRsp.getMsg());
        }

        List<SqlFieldsVO> fieldList = (List<SqlFieldsVO>) fieldListRsp.getData();

        JSONObject columnTableRef = null;
        try {
            columnTableRef = SqlUtil.getColumnTableRefJo(sql);
        } catch (JSQLParserException e) {
            return ResultMsg.ERROR(ExceptionUtil.getExceptionMessage((Throwable) e));
        }

        JSONObject defaultTable = columnTableRef.getJSONObject("default");

        String tableAlias = "";
        if (defaultTable != null) {
            tableAlias = defaultTable.getString("tableAlias");
        }


        for (SqlFieldsVO sqlFieldVO : fieldList) {
            String column = sqlFieldVO.getFieldName().toLowerCase() + "." + sqlFieldVO.getName().toLowerCase();
            if (!columnTableRef.containsKey(column) && StringUtil.isEmpty(sqlFieldVO.getTableAlias())) {
                sqlFieldVO.setTableAlias(tableAlias);

                continue;
            }
            JSONObject jo = (JSONObject) columnTableRef.get(column);

            sqlFieldVO.setTableAlias(jo.getString("tableAlias"));
            if (jo.containsKey("tableName")) {
                sqlFieldVO.setTableName(jo.getString("tableName"));
            }
        }
        return ResultMsg.SUCCESS(fieldList);
    }
    private String getSql(String sql) {
        String regex = "\\$\\{\\w+\\}";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(sql);
        while (m.find()) {
            String whereParam = m.group();

            sql = sql.replace(whereParam, "'' or 1=1 or 1=''");
            sql = sql.replace("'''", "''");
        }


        regex = "\\{\\w+\\}";
        p = Pattern.compile(regex);
        m = p.matcher(sql);
        while (m.find()) {
            String whereParam = m.group();

            sql = sql.replace(whereParam, " 1=1 ");
        }

        return sql;
    }

    public ResultMsg<String> save(FormCustSql formCustSql) {
        String id = formCustSql.getId();
        ResultMsg<String> checkParams = this.checkParams(formCustSql, id);
        if (!checkParams.getIsOk()) {
            return checkParams;
        } else {
            formCustSql.setButtons(JSONObjectUtil.toListString(formCustSql.getButtons(), SqlButtonVO.class));
            formCustSql.setConditions(JSONObjectUtil.toListString(formCustSql.getConditions(), SqlConditionVO.class));
            if (formCustSql.getCustForm() != null) {
                formCustSql.setFormKey(formCustSql.getCustForm().getFormKey());
            }

            if (StringUtil.isEmpty(id)) {
                id = IdUtil.getSuid();
                formCustSql.setCreateBy(ContextUtil.getCurrentUserId());
                formCustSql.setCreator(ContextUtil.getCurrentUserName());
                formCustSql.setCreateTime(new Date());
                formCustSql.setId(id);
                formCustSql.setVersion(1);
                // 增加检查module（若无则从group获取module值）2021/08/31
                checkModuleInFormCustSql(formCustSql);
                this.create(formCustSql);
                this.saveSqlFields(formCustSql, id);
                this.saveCustSqlFormRelation(formCustSql);
                return ResultMsg.SUCCESS(id);
            } else {
                formCustSql.setUpdateBy(ContextUtil.getCurrentUserId());
                formCustSql.setUpdator(ContextUtil.getCurrentUserName());
                formCustSql.setUpdateTime(new Date());
                formCustSql.setVersion(formCustSql.getVersion() + 1);
                this.update(formCustSql);
                this.saveSqlFields(formCustSql, id, false);
                this.saveCustSqlFormRelation(formCustSql);
                return ResultMsg.SUCCESS(id);
            }
        }
    }
    /**
     * 检查module（若无则从group获取module值）
     * @param formCustSql
     */
    public void checkModuleInFormCustSql(FormCustSql formCustSql){
        JSONObject expandJo = JSONObjectUtil.parseExpand(formCustSql.getExpand());
        String busModule = "etech";
        if(expandJo.containsKey("busModule")){
            busModule =expandJo.getString("busModule");
        }
        if(StringUtil.isNotEmpty(formCustSql.getGroupId())){
            SysTreeNode treeNode = sysTreeNodeDao.get(formCustSql.getGroupId());
            if(treeNode!=null){
                // 本级
                if(StringUtil.isNotEmpty(treeNode.getBusModule())){
                    busModule = treeNode.getBusModule();
                    // 查找上一级
                }else if(StringUtil.isNotEmpty(treeNode.getParentId())){
                    String parentId = treeNode.getParentId();
                    treeNode = sysTreeNodeDao.get(parentId);
                    if(treeNode!=null && StringUtil.isNotEmpty(treeNode.getBusModule())){
                        busModule = treeNode.getBusModule();
                    }
                }
            }
        }
        expandJo.put("busModule", busModule);
        formCustSql.setExpand(JSONObjectUtil.toJsonStr(expandJo));
    }

    void checkBtnExport(String code, FormCustSql formCustSql, boolean canExport){

        String buttons = formCustSql.getButtons();
        List<SqlButtonVO> buttonList = null;
        if (StringUtil.isNotEmpty(buttons)) {
            buttonList = JSONObjectUtil.toList(buttons, SqlButtonVO.class);
            for (SqlButtonVO sqlButtonVO : buttonList) {
                sqlButtonVO.setDataChange(null);
                // 找到"导出"按钮, 可以导出则退出，不允许导出则删除
                if ("xx:export".equals(sqlButtonVO.getAlias())) {
                    if(canExport){
                        return;
                    }else{
                        buttonList.remove(sqlButtonVO);
                        formCustSql.setButtons(JSONArray.toJSONString(buttonList));
                        return;
                    }
                }
            }
        }

        if (canExport) {
            if(buttonList==null){
                buttonList = new ArrayList<SqlButtonVO>();
            }
            // 动态添加 导出 按钮 (放到第一个)
            SqlButtonVO expBtn = createExpButton(code);
            buttonList.add(0, expBtn);
            formCustSql.setButtons(JSONArray.toJSONString(buttonList));
        }
    }

    /**
     * @deprecated
     */
    void checkAndAddExport(String code, FormCustSql formCustSql, boolean withUpdate){
        boolean needAddExport = true;
        String buttons = formCustSql.getButtons();
        List<SqlButtonVO> buttonList = null;
        if (StringUtil.isNotEmpty(buttons)) {
            buttonList = JSONObjectUtil.toList(buttons, SqlButtonVO.class);
            for (SqlButtonVO sqlButtonVO : buttonList) {
                sqlButtonVO.setDataChange(null);
                if ("xx:export".equals(sqlButtonVO.getAlias())) {
                    needAddExport = false;
                }
            }
        }
        if (needAddExport) {
            if(buttonList==null){
                buttonList = new ArrayList<SqlButtonVO>();
            }
            // 动态添加 导出 按钮 (放到第一个)
            SqlButtonVO expBtn = createExpButton(code);
            buttonList.add(0, expBtn);
            formCustSql.setButtons(JSONArray.toJSONString(buttonList));

            // 添加导出按钮需要保存到配置中，补救历史数据 2021/12/09
            if(withUpdate){
                FormCustSql formCustSql2 = getByCode(code, true);
                formCustSql2.setButtons(JSONArray.toJSONString(buttonList));
                saveSqlFields(formCustSql2, formCustSql2.getId());
            }

        }
    }
    private SqlButtonVO createExpButton(String code) {
        SqlButtonVO expBtn = new SqlButtonVO();
        expBtn.setAlias("xx:export");
        expBtn.setName("导出");
        expBtn.setType("2");
        expBtn.setMustSelect(0);
        expBtn.setClickType("0");
        expBtn.setIcon("fa-detail");
        expBtn.setBtncss("btn-primary");
        expBtn.setJoinBtnRight(0);
        //expBtn.setJoinBtnRight(1);   //导出按钮默认需要菜单权限控制
        //expBtn.setUrl("/etech/formCustSql/view/export_"+code);
        expBtn.setUrl("javascript:scope.exportData(scope);");
        expBtn.setExp("true");
        expBtn.setExpand("{\"hrefSetting\":{\"width\":\"100\",\"heightUnit\":\"%\",\"openType\":\"0\",\"height\":\"100\"}}");
        return expBtn;
    }
    protected void saveSqlFields(FormCustSql formCustSql, String id){
        saveSqlFields(formCustSql, id, true);
    }
    protected void saveSqlFields(FormCustSql formCustSql, String id, boolean isNew) {
        // 增加增量修改检查
        List<FormCustSqlFields> fieldsList = formCustSql.getFieldsList();
        Set<String> fieldNameSet = new HashSet<>();  //检查重复字段
        // create/update/delete
        List<FormCustSqlFields> fieldsListCreate = new ArrayList<>();
        List<FormCustSqlFields> fieldsListUpdate = new ArrayList<>();
        List<String> fieldIdsDel = null;

        if(isNew){
            // all create
            //fieldsListCreate.addAll(fieldsList);
            for (FormCustSqlFields formCustSqlFields : fieldsList) {
                //防止重复创建
                String fieldName = formCustSqlFields.getFieldName();
                if(fieldNameSet.contains(fieldName)){
                    continue;
                }else {
                    fieldNameSet.add(fieldName);
                }
                // 后端代码表字段类型改为字符串以支持按label筛选
                if(18==formCustSqlFields.getControlType()){
                    if(!"varchar".equalsIgnoreCase(formCustSqlFields.getDataType())){
                        formCustSqlFields.setDataType("varchar");
                    }
                }
                fieldsListCreate.add(formCustSqlFields);
            }
        }else{
            List<FormCustSqlFields> oldFieldsList = this.formCustSqlFieldsManager.getListBySqlId(id);
            // 假定全删除
            fieldIdsDel = oldFieldsList.stream().map(BaseModel::getId).collect(Collectors.toList());
            for (FormCustSqlFields formCustSqlFields : fieldsList) {
                String fielDid = formCustSqlFields.getId();
                String fieldName = formCustSqlFields.getFieldName();
                // 后端代码表字段类型改为字符串以支持按label筛选
                if(18==formCustSqlFields.getControlType()){
                    if(!"varchar".equalsIgnoreCase(formCustSqlFields.getDataType())){
                        formCustSqlFields.setDataType("varchar");
                    }
                }
                if(fieldIdsDel.contains(fielDid)){
                    //已存在则更新
                    fieldIdsDel.remove(fielDid);
                    formCustSqlFields.setId(fielDid);
                    fieldsListUpdate.add(formCustSqlFields);
                    fieldNameSet.add(fieldName);
                }else{
                    //不存在创建
                    //防止重复创建
                    if(fieldNameSet.contains(fieldName)){
                        continue;
                    }else {
                        fieldNameSet.add(fieldName);
                    }
                    fieldsListCreate.add(formCustSqlFields);
                }
            }
            // 删除未使用的（已排除更新字段）
            this.formCustSqlFieldsManager.removeByIdList(fieldIdsDel);
        }

        // 检查新建列表
        if(CollectionUtil.isNotEmpty(fieldsListCreate)){
            for (FormCustSqlFields formCustSqlFields : fieldsListCreate) {
                formCustSqlFields.setId(IdUtil.getSuid());
                formCustSqlFields.setCreateBy(ContextUtil.getCurrentUserId());
                formCustSqlFields.setCreator(ContextUtil.getCurrentUserName());
                formCustSqlFields.setCreateTime(new Date());
                formCustSqlFields.setSqlId(id);
                this.formCustSqlFieldsManager.create(formCustSqlFields);
            }
        }
        // 检查更新列表
        if(CollectionUtil.isNotEmpty(fieldsListUpdate)){
            for (FormCustSqlFields formCustSqlFields : fieldsListUpdate) {
                formCustSqlFields.setSqlId(id);
                formCustSqlFields.setUpdateBy(ContextUtil.getCurrentUserId());
                formCustSqlFields.setUpdator(ContextUtil.getCurrentUserName());
                formCustSqlFields.setUpdateTime(new Date());
                this.formCustSqlFieldsManager.update(formCustSqlFields);
            }
        }
    }


    private ResultMsg<String> checkParams(FormCustSql formCustSql, String id) {
        DefaultQueryFilter defaultQueryFilter = new DefaultQueryFilter();
        if (StringUtil.isNotEmpty(id)) {
            defaultQueryFilter.addFilter("id_", id, QueryOP.NOT_EQUAL);
        }

        String code = formCustSql.getCode();
        defaultQueryFilter.addFilter("code_", code, QueryOP.EQUAL);
        List<FormCustSql> query = this.formCustSqlDao.query(defaultQueryFilter);
        if (!query.isEmpty()) {
            return ResultMsg.ERROR("编码已存在,code:" + code);
        }


        String tableName = formCustSql.getTableName();
        if (StringUtil.isEmpty(tableName)) {
            this.logger.error("自定义SQL的主表不存在,code:{}", code);
            return ResultMsg.ERROR("自定义SQL的主表不存在");
        }

        List<FormCustSqlFields> newFieldsList = formCustSql.getFieldsList();


        Map<String, String> fieldNameColumnMap = newFieldsList.stream().filter(fields -> Util.equals(fields.getTableName(), tableName)).collect(Collectors.toMap(FormCustSqlFields::getFieldName, FormCustSqlFields::getName));


        String pkName = formCustSql.getPkName();
        if (StringUtil.isEmpty(fieldNameColumnMap.get(pkName))) {
            this.logger.error("自定义SQL的主键不存在,code:{},tableName:{},pkName:{}", code, tableName, pkName);
            return ResultMsg.ERROR("自定义SQL的主键不存在,tableName:" + tableName + ",pkName:" + pkName);
        }

        List<String> columnList = newFieldsList.stream().map(FormCustSqlFields::getName).collect(Collectors.toList());

        // 增加检查导出按钮
        boolean canExport = "1".equals(formCustSql.getCanExport() != null ? formCustSql.getCanExport().toString() : "0");
        checkBtnExport(code, formCustSql, canExport);

        List<SqlButtonVO> buttonList = JSONObjectUtil.toList(formCustSql.getButtons(), SqlButtonVO.class);

        if (CollectionUtils.isEmpty(buttonList)) {
            return ResultMsg.SUCCESS();
        }


        List<SqlButtonVO> uniqueAliasButtonList = buttonList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> {
                    return new TreeSet<SqlButtonVO>(Comparator.comparing(SqlButtonVO::getAlias));
                }), ArrayList::new));

        if (buttonList.size() != uniqueAliasButtonList.size()) {
            this.logger.error("请检查按钮别名是否重复,code:{},tableName:{},pkName:{}", code, tableName, pkName);
            return ResultMsg.ERROR("请检查自定义按钮别名是否重复");
        }

        if (!CollectionUtils.isEmpty(buttonList)) {
            for (SqlButtonVO sqlButtonVO : buttonList) {
                if (Util.equals(sqlButtonVO.getClickType(), Integer.valueOf(1))) {
                    String dataChangeStr = sqlButtonVO.getDataChange();
                    if(StringUtil.isEmpty(dataChangeStr)){
                        continue;
                    }
                    String[] dataChangeArray = dataChangeStr.split(";");

                    for (String dataChange : dataChangeArray) {
                        String[] changeData = dataChange.split("=");
                        String buttonAlias = sqlButtonVO.getAlias();
                        if (changeData.length != 2) {
                            this.logger.error("自定义按钮数值变化配置不正确,code:{},btnAlias:{},dataChange:{}", code, buttonAlias, dataChange);

                            return ResultMsg.ERROR("自定义按钮数值变化配置不正确:" + dataChange);
                        }
                        String fieldName = changeData[0];
                        String value = changeData[1];

                        if (!columnList.contains(fieldName) && !fieldNameColumnMap.containsKey(fieldName)) {
                            this.logger.error("自定义按钮数值变化配置不正确,主表中找不到对应的字段,code:{},btnAlias:{},dataChange:{},column:{}", code, buttonAlias, dataChange, fieldName);

                            return ResultMsg.ERROR("自定义按钮数值变化配置不正确,主表中找不到对应的字段:" + dataChange);
                        }
                        if (StringUtil.isEmpty(value)) {
                            return ResultMsg.ERROR("自定义按钮数值变化配置不正确,数据不能为空:" + dataChange);
                        }
                    }
                }
            }
        }

        return ResultMsg.SUCCESS();
    }

    private void saveCustSqlFormRelation(FormCustSql formCustSql) {
        if (!StringUtil.isEmpty(formCustSql.getFormKey())) {
            FormCustSqlRelation formCustSqlRelation = formCustSql.getCustForm();
            FormCustSqlRelation existsRelation = this.formCustSqlRelationMananger.getByFormKey(formCustSql.getFormKey());
            if (existsRelation != null && existsRelation.getListId().equals(formCustSqlRelation.getId())) {
                FormCustSql formSql = this.get(existsRelation.getId());
                String formSqlName = formSql == null ? "未知???" : formSql.getName();
                throw new BusinessMessage("表单[" + formCustSqlRelation.getFormName() + "]已经被自定义列表[" + formSqlName + "] 使用，请重新创建一个新的表单，为当前列表专用！");
            } else {
                formCustSqlRelation.setListId(formCustSql.getId());
                if (StringUtil.isEmpty(formCustSqlRelation.getId())) {
                    this.formCustSqlRelationMananger.create(formCustSqlRelation);
                } else {
                    this.formCustSqlRelationMananger.update(formCustSqlRelation);
                }

            }
        }
    }


    private Set<String> getShowFieldsInTodo() {
        Set<String> fields = new HashSet<>();

        fields.add("task_id_");
        fields.add("remain_days_");
        fields.add("master_group_name_");
        fields.add("create_time_");
        fields.add("plan_complete_day_");

        return fields;
    }

    private Set<String> getRemoveFieldsInTodo() {
        Set<String> fields = new HashSet<>();

        //fields.add("subject_");
        //fields.add("node_id_");
        fields.add("assignee_id_");
        fields.add("biz_id_");
        fields.add("biz_code_");
        fields.add("def_key_");
        //fields.add("def_name_");
        fields.add("master_group_");
        fields.add("due_time_");
        fields.add("cal_days_time_");
        fields.add("assignee_ids_");
        return fields;
    }



}
